package org.ysling.litemall.core.tasks.service;
/**
 *  Copyright (c) [ysling] [927069313@qq.com]
 *  [litemall-plus] is licensed under Mulan PSL v2.
 *  You can use this software according to the terms and conditions of the Mulan PSL v2.
 *  You may obtain a copy of Mulan PSL v2 at:
 *              http://license.coscl.org.cn/MulanPSL2
 *  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 *  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 *  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *  See the Mulan PSL v2 for more details.
 */
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ysling.litemall.core.system.SystemConfig;
import org.ysling.litemall.core.tasks.*;
import org.ysling.litemall.db.domain.LitemallCoupon;
import org.ysling.litemall.db.domain.LitemallCouponUser;
import org.ysling.litemall.db.domain.LitemallGrouponRules;
import org.ysling.litemall.db.domain.LitemallOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.ysling.litemall.db.service.*;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 检测订单状态
 */
@Component
public class TaskJob {
    private final Log logger = LogFactory.getLog(TaskJob.class);

    @Autowired
    private LitemallGrouponRulesService rulesService;
    @Autowired
    private LitemallOrderService orderService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private LitemallCouponService couponService;
    @Autowired
    private LitemallCouponUserService couponUserService;

    /**
     * 自动确认收货延时队列检查
     * <p>
     * 定时时间是每天凌晨1点。
     *
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void checkOrderUnconfirmed() {
        logger.info("系统定时任务 -> [开始检查-订单自动确认收货]");
        List<LitemallOrder> orderList = orderService.queryUnconfirmed();
        for(LitemallOrder order : orderList){
            LocalDateTime ship = order.getShipTime();
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expire =  ship.plusDays(SystemConfig.getOrderUnconfirmed());
            if(expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new OrderUnconfirmedTask(order.getId(), 0));
            }
            else{
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                logger.info(String.format("系统定时任务 -> [查询-订单自动确认收货][超时时间=%s毫秒]" , delay));
                taskService.addTask(new OrderUnconfirmedTask(order.getId(), delay));
            }
        }

        logger.info(String.format("系统定时任务 -> [结束检查-订单自动确认收货][检查结果={数量%s}]" , orderList.size()));
    }

    /**
     * 团购延时队列检查
     * <p>
     * 定时时间是每天凌晨2点。
     *
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void checkGrouponRuleExpired() {
        logger.info("系统定时任务 -> [开始检查-团购规则过期]");
        List<LitemallGrouponRules> grouponRulesList = rulesService.queryExpired();
        for(LitemallGrouponRules grouponRules : grouponRulesList){
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expire =  grouponRules.getExpireTime();
            if(expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new GrouponRuleExpiredTask(grouponRules.getId(), 0));
            }
            else{
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                logger.info(String.format("系统定时任务 -> [查询-团购规则过期][超时时间=%s毫秒]" , delay));
                taskService.addTask(new GrouponRuleExpiredTask(grouponRules.getId(), delay));
            }
        }

        logger.info(String.format("系统定时任务 -> [结束检查-团购规则过期][检查结果={数量%s}]" , grouponRulesList.size()));
    }

    /**
     * 订单超时支付延时队列检查
     * <p>
     * 定时时间是每天凌晨3点。
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void checkOrderUnpaid() {
        logger.info("系统定时任务 -> [开始检查-订单支付超时]");
        List<LitemallOrder> orderList = orderService.queryUnpaid();
        for(LitemallOrder order : orderList){
            LocalDateTime add = order.getAddTime();
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expire =  add.plusMinutes(SystemConfig.getOrderUnpaid());
            if(expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new OrderUnpaidTask(order.getId(), 0));
            }
            else{
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                logger.info(String.format("系统定时任务 -> [查询-订单支付超时][超时时间=%s毫秒]" , delay));
                taskService.addTask(new OrderUnpaidTask(order.getId(), delay));
            }
        }
        logger.info(String.format("系统定时任务 -> [结束检查-订单支付超时][检查结果={数量%s}]" , orderList.size()));
    }

    /**
     * 可评价订单商品超期
     * <p>
     * 定时时间是每天凌晨4点。
     */
    @Scheduled(cron = "0 0 4 * * ?")
    public void checkOrderComment() {
        logger.info("系统定时任务 -> [开始检查-订单评论超时]");
        //查询所有评论超时订单
        List<LitemallOrder> orderList = orderService.queryComment();
        for(LitemallOrder order : orderList){
            LocalDateTime add = order.getConfirmTime();
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expire =  add.plusDays(SystemConfig.getOrderComment());
            if(expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new OrderCommentTask(order.getId(), 0));
            }
            else{
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                logger.info(String.format("系统定时任务 -> [查询-订单评论超时][超时时间=%s毫秒]" , delay));
                taskService.addTask(new OrderCommentTask(order.getId(), delay));
            }
        }
        logger.info(String.format("系统定时任务 -> [结束检查-订单评论超时][检查结果={数量%s}]" , orderList.size()));
    }

    /**
     * 检查优惠券是否已经过期
     * <p>
     * 定时时间是每天凌晨5点。
     */
    @Scheduled(cron = "0 0 5 * * ?")
    public void checkCouponExpired() {
        logger.info("系统定时任务 -> [开始检查-优惠券是否已经过期]");
        //查询所有已经过期优惠券
        List<LitemallCoupon> couponList = couponService.queryExpired();
        for(LitemallCoupon coupon : couponList){
            LocalDateTime expire = coupon.getEndTime();
            LocalDateTime now = LocalDateTime.now();
            if(expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new CouponExpiredTask(coupon.getId(), 0));
            }
            else{
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                logger.info(String.format("系统定时任务 -> [查询-优惠券是否已经过期][超时时间=%s毫秒]" , delay));
                taskService.addTask(new CouponExpiredTask(coupon.getId(), delay));
            }
        }
        logger.info(String.format("系统定时任务 -> [结束检查-优惠券是否已经过期][检查结果={数量%s}]" , couponList.size()));
    }

    /**
     * 检查用户优惠券是否已经过期
     * <p>
     * 定时时间是每天凌晨6点。
     */
    @Scheduled(cron = "0 0 6 * * ?")
    public void checkCouponUserExpired() {
        logger.info("系统定时任务 -> [开始检查-用户优惠券是否已经过期]");
        //查询所有已经过期优惠券
        List<LitemallCouponUser> couponList = couponUserService.queryExpired();
        for(LitemallCouponUser couponUser : couponList){
            LocalDateTime expire = couponUser.getEndTime();
            LocalDateTime now = LocalDateTime.now();
            if(expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new CouponUserExpiredTask(couponUser.getId(), 0));
            }
            else{
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                logger.info(String.format("系统定时任务 -> [查询-用户优惠券是否已经过期][超时时间=%s毫秒]" , delay));
                taskService.addTask(new CouponUserExpiredTask(couponUser.getId(), delay));
            }
        }
        logger.info(String.format("系统定时任务 -> [结束检查-用户优惠券是否已经过期][检查结果={数量%s}]" , couponList.size()));
    }
}
